
历史上，只有两种值类别:左值和右值。左值是指存储在内存或机器寄存器中实际值的表达式，例如表达式x，其中x是变量名。这些表达式可以修改，从而允许更新存储的值。若x是一个int类型的变量，下面的赋值会将x的值替换为7:

\begin{lstlisting}[style=styleCXX]
x = 7;
\end{lstlisting}

术语左值来自于这些表达式在赋值中可能扮演的角色:字母“l”代表“左手边”，因为(在C中)只有左值可能出现在赋值的左手边。相反，右值(“r”代表“右手边”)只能出现在赋值表达式的右手边。

1989年C语言标准化后，情况发生了变化:当int const仍然是存储在内存中的值时，不能出现在赋值操作的左侧:

\begin{lstlisting}[style=styleCXX]
int const x; // x is a nonmodifiable lvalue
x = 7; // ERROR: modifiable lvalue required on the left
\end{lstlisting}

C++进一步改变了这一点:类的右值可以出现在赋值的左侧。这样的赋值实际上是对类的适当赋值操作符的函数调用，而不是对标量类型的“简单”赋值，因此遵循(单独的)成员函数调用规则。

由于所有这些变化，术语左值现在有时称为本地化值。引用变量的表达式并不是唯一一种左值表达式。另一类左值表达式包括指针解引用操作(例如，*p)和类对象成员的表达式(例如，p\texttt{->}data)。解引用操作指向存储在指针引用地址的值。即使调用返回用\&声明的“传统”左值引用类型的函数也是左值。例如(详见第B.4节):

\begin{lstlisting}[style=styleCXX]
std::vector<int> v;
v.front() // yields an lvalue because the return type is an lvalue reference
\end{lstlisting}

字符串字面值也是(不可修改的)左值。

右值是纯粹的数学值(如7或字符'a')，不一定有相关的存储;它们的存在就为了计算，但当使用它们时就不能再引用。除了字符串字面量(例如，7，'a'， true, nullptr)之外的字面值都是右值，就像许多内置算术计算(例如，x + 5对于整数类型的x)和调用按值返回结果的函数一样，所有的临时变量都是右值(不过，这不适用于引用它们的命名引用)。

\subsubsubsection{B.1.1\hspace{0.2cm}左值到右值的转换}

由于右值的短暂性，只能出现在赋值语句(“简单”)的右侧:赋值语句7 = 8是没有意义的，因为不允许重新定义数学上的7。另一方面，左值似乎没有同样的限制:当x和y是兼容类型的变量时，可以计算赋值x = y，即使表达式x和y都是左值。

赋值x = y可行，因为右边的表达式y进行了隐式转换，称为左值到右值转换。顾名思义，左值可以转换为右值，并通过从与左值相关联的存储或寄存器中读取该左值，来生成相同类型的右值。因此，这种转换完成了两件事:第一，确保左值可以在任何需要右值的地方使用(作为赋值的右手边或在数学表达式中，如x + y)。第二，确定了在程序中(优化之前)编译器发出“load”指令从内存中读取值的位置。


















